#include <iostream>
#include <cstdbool>
#include <cstring>
#include "StdMyString.h"


StdMyString::StdMyString()
{
    size = 10;
    str = new char[size];
    len = 0;
    memset(str, 0, 10);
}

StdMyString::StdMyString(const char* str)
{
    len = strlen(str);
    size = (len/10 + 1) * 10;
    this->str = new char[size];
    strcpy(this->str, str);
}

StdMyString::StdMyString(const StdMyString& str)
{
    this->len = str.len;
    this->size = str.size;
    this->str = new char[this->size];
    strcpy(this->str, str.str);
}

StdMyString::~StdMyString()
{
    delete str;
}

StdMyString StdMyString::GetString(int start, int end)
{
    if(start >= 0 && start < end && end <= len)
    {
        StdMyString s;
        delete s.str;

        s.len = end - start;
        s.size = (s.len / 10 + 1) * 10;
        s.str = new char[s.size];
        strncpy(s.str, &this->str[start], s.len);
        s.str[s.len] = '\0';
        return s;
    }
    return StdMyString(); 
}

void StdMyString::InsertByIndex(int index, const char* str)
{
    if(index < 0 || index > len)
    {
        std::cout << "InsertyByIndex invalid index :" << index << std::endl;
    }

    char* newStr = new char[this->len + strlen(str)];

    sprintf(newStr, "%s%s%s", this->GetString(0, index).str, str, this->GetString(index, len).str);
    delete this->str;
    this->str = newStr;
    this->len  = this->len + strlen(str);
    this->size = (this->len / 10 + 1) * 10;
}

void StdMyString::InsertByIndex(int index, const StdMyString& str)
{
    this->InsertByIndex(index, str.str);
}


char StdMyString::At(int index)
{
    if(index < 0 || index >= len)
    {
        std::cout << "At : invalid index" << index << std::endl;
        return -1;
    }
    else
    {
        return this->str[index];
    }
}

StdMyString::operator int()
{
    return atoi(this->str);
}

StdMyString::operator float()
{
    return atof(this->str);
}

char& StdMyString::operator [](int index)
{
    if(index < 0 || index >= len)
    {
        std::cout << "operator[] : invalid index" << index << std::endl;
        return this->str[strlen(this->str) + 1];
    }
    else
    {
        return this->str[index];
    }
}

bool StdMyString::contaions(const StdMyString& str)
{
    if(strstr(this->str, str.str) == NULL)
        return false;
    else
        return true;
}

bool StdMyString::contaions(const char* str)
{
    if(strstr(this->str, str) == NULL)
        return false;
    else
        return true;
}

int StdMyString::Find(const char* str)
{
    char* ptr = strstr(this->str, str);
    if(ptr == nullptr)
        return -1;
    else
        return ptr - this->str;
}

int StdMyString::Find(const StdMyString& str)
{
    char* ptr = strstr(this->str, str.str);
    if(ptr == nullptr)
        return -1;
    else
        return ptr - this->str;
}

StdMyString StdMyString::operator +(const char* str)
{
    StdMyString newStr;
    delete newStr.str;
    newStr.len = this->len + strlen(str);
    newStr.size = (newStr.len / 10 + 1) * 10;
    newStr.str = new char[newStr.size];
    strcpy(newStr.str, this->str);
    strcat(newStr.str, str);
    return newStr;
}

StdMyString StdMyString::operator +(const StdMyString& str)
{
    StdMyString newStr;
    delete newStr.str;
    newStr.len = this->len + strlen(str.str);
    newStr.size = (newStr.len / 10 + 1) * 10;
    newStr.str = new char[newStr.size];
    strcpy(newStr.str, this->str);
    strcat(newStr.str, str.str);
    return newStr;
}

StdMyString& StdMyString::operator =(const StdMyString& str)
{

    this->size = str.size;
    this->len = str.len;
    delete this->str;
    this->str = new char[this->size];
    strcpy(this->str, str.str);
    return *this;
}

StdMyString& StdMyString::operator =(const char* str)
{
    delete this->str;
    len = strlen(str);
    size = (len / 10 + 1) * 10;
    this->str = new char[size];
    strcpy(this->str, str);
    return *this;
}

void StdMyString::operator +=(const char* str)
{
    if(this->size > strlen(str) + this->len)
    {
        strcat(this->str, str);
    }
    else
    {
        this->len = strlen(str) + this->len;
        this->size = (len / 10 + 1) * 10;
        char* newStr = new char [this->size];
        strcpy(newStr, this->str);
        strcat(newStr, str);
        delete this->str;
        this->str = newStr;
    }
}

void StdMyString::operator +=(const StdMyString& str)
{
    *this += str.str;
}

bool StdMyString::operator ==(const StdMyString& str)
{
    if(strcmp(this->str, str.str) == 0)
        return true;
    else
        return false;
}

bool StdMyString::operator ==(const char* str)
{
    if(strcmp(this->str, str) == 0)
        return true;
    else
        return false;
}

bool StdMyString::operator !=(const StdMyString& str)
{
    if(strcmp(this->str, str.str) == 0)
        return false;
    else
        return true;
}

bool StdMyString::operator !=(const char* str)
{
    if(strcmp(this->str, str) == 0)
        return false;
    else
        return true;
}

bool StdMyString::operator >(const StdMyString& str)
{
    if(strcmp(this->str, str.str) > 0)
        return true;
    else
        return false;
}

bool StdMyString::operator >(const char* str)
{
    if(strcmp(this->str, str) > 0)
        return true;
    else
        return false;
}

bool StdMyString::operator <(const StdMyString& str)
{
    if(strcmp(this->str, str.str) < 0)
        return true;
    else
        return false;
}

bool StdMyString::operator <(const char* str)
{
    if(strcmp(this->str, str) < 0)
        return true;
    else
        return false;
}

std::ostream& operator <<(std::ostream& out, const StdMyString& str)
{
    out << str.str;
    return out;
}

StdMyString StdMyString::Number(int value)
{
    StdMyString s;
    sprintf(s.str, "%d", value);
    s.len = strlen(s.str);
    return s;
}

StdMyString StdMyString::Number(float value)
{
    StdMyString s;
    sprintf(s.str, "%f", value);
    s.len = strlen(s.str);
    return s;
}